package reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * 反射机制
 * 反射是java的动态机制,它允许我们程序在[运行期间]确定方法的调用,属性的操作,对象的实例化等
 * 反射机制提高了代码的灵活度,但是运行效率相对较低,开销大,因此不能过度的依赖
 *
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
            使用反射机制的第一步:获取要操作的类的类对象
            Class类的示例
            Class的每一个实例用于表示JVM加载的一个类的相关信息
            并且每个被JVM加载的类[都有且只有一个]类对象与之对应
            通过获取一个类的类对象,我们可以了解其对应类的一切内容:类名,包信息,构造器信息,方法信息,属性信息等等
            从而在程序运行期间进行相关操作

            如何获取一个类的类对象?
            1:类名.class
            例如:
                Class cls = String.class;//获取String的类对象
                Class cls = int.class;//获取int类型的类对象 ,注意:基本类型仅有这一种方式获取

            2:对象.getClass()
            3:Class.forName(String className)
              例如:
              Class cls = Class.forName("java.lang.String");
              根据类名获取它的类对象,类名必须是完全限定名,即:"包名.类名"
            4:后期还可以使用类加载器ClassLoader做更多高阶操作
         */
//        Class cls = String.class;//获取字符串的类对象
//        Class cls = ArrayList.class;

        //指定类的完全限定名方式获取一个类的类对象
//        Class cls = Class.forName("java.lang.String");
//        Class cls = Class.forName("java.util.ArrayList");

        /*
            java.lang.String
            java.util.HashMap
            java.io.FileInputStream
         */
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个类名:");
        String className = scanner.nextLine();
        Class cls = Class.forName(className);


        //通过类对象获取其表示的类的完全限定名
        String name = cls.getName();
        System.out.println(name);
        //也可以仅获取类名
        name = cls.getSimpleName();
        System.out.println(name);

        /*
            通过类对象的方法:
            Package getPackage()
            可以获取当前类对象所表示的类的包信息,每个包信息用一个Package对象表示.
            Package也是反射对象之一,它的每一个实例用于表示一个包信息
         */
        Package pack = cls.getPackage();
        //通过包对象获取对应的包名
        String packName = pack.getName();
        System.out.println(packName);

        /*
            Method[] getMethods()
            该方法可以获取当前类对象所表示的类中的所有公开方法(包含从超类继承的方法)

            Method是方法对象,它的每一个实例用于表示某个类中的某个方法,也是反射对象之一
         */
        Method[] methods = cls.getMethods();
        System.out.println("一共有:"+methods.length+"个方法");
        for(Method method : methods){
            System.out.println(method.getName());
        }
    }
}









